using System;

namespace LS.Digitize
{
    public class EnumSerializer: Serializer
    {
        public static EnumSerializer Instance { get; internal set; }

        public override bool IsPrimitive => true;
        public override bool IsEnum => true;
        private Type m_UnderlyingType = null;
        public Type UnderlyingType => m_UnderlyingType;
        
        public EnumSerializer(Type type) : base(type)
        {
            Instance = this;
            m_UnderlyingType = Enum.GetUnderlyingType(type);
        }
        
        public override void Write(IWriter writer, object obj)
        {
            if(UnderlyingType == typeof(int)) writer.WritePrimitive((int)obj);
            else if(UnderlyingType == typeof(bool))		writer.WritePrimitive((bool)obj);
            else if(UnderlyingType == typeof(byte))		writer.WritePrimitive((byte)obj);
            else if(UnderlyingType == typeof(char))		writer.WritePrimitive((char)obj);
            else if(UnderlyingType == typeof(decimal))	writer.WritePrimitive((decimal)obj);
            else if(UnderlyingType == typeof(double))	writer.WritePrimitive((double)obj);
            else if(UnderlyingType == typeof(float))	writer.WritePrimitive((float)obj);
            else if(UnderlyingType == typeof(long))		writer.WritePrimitive((long)obj);
            else if(UnderlyingType == typeof(sbyte))	writer.WritePrimitive((sbyte)obj);
            else if(UnderlyingType == typeof(short))	writer.WritePrimitive((short)obj);
            else if(UnderlyingType == typeof(uint))		writer.WritePrimitive((uint)obj);
            else if(UnderlyingType == typeof(ulong))	writer.WritePrimitive((ulong)obj);
            else if(UnderlyingType == typeof(ushort))	writer.WritePrimitive((ushort)obj);
            else
                throw new System.InvalidCastException($"Underlying type {UnderlyingType} of Enum {DataType} is not supported.");

        }

        public override object Read(IReader reader)
        {
            if(UnderlyingType == typeof(int))		return Enum.ToObject (DataType, reader.ReadInt());
            else if(UnderlyingType == typeof(bool))		return Enum.ToObject (DataType, reader.ReadBool());
            else if(UnderlyingType == typeof(byte))		return Enum.ToObject (DataType, reader.ReadByte());
            else if(UnderlyingType == typeof(char))		return Enum.ToObject (DataType, reader.ReadChar());
            else if(UnderlyingType == typeof(decimal))	return Enum.ToObject (DataType, reader.ReadDecimal());
            else if(UnderlyingType == typeof(double))	return Enum.ToObject (DataType, reader.ReadDouble());
            else if(UnderlyingType == typeof(float))	return Enum.ToObject (DataType, reader.ReadFloat());
            else if(UnderlyingType == typeof(long))		return Enum.ToObject (DataType, reader.ReadLong());
            else if(UnderlyingType == typeof(sbyte))	return Enum.ToObject (DataType, reader.ReadSbyte());
            else if(UnderlyingType == typeof(short))	return Enum.ToObject (DataType, reader.ReadShort());
            else if(UnderlyingType == typeof(uint))		return Enum.ToObject (DataType, reader.ReadUint());
            else if(UnderlyingType == typeof(ulong))	return Enum.ToObject (DataType, reader.ReadUlong());
            else if(UnderlyingType == typeof(ushort))	return Enum.ToObject (DataType, reader.ReadUshort());
            else
                throw new System.InvalidCastException($"Underlying type {UnderlyingType} of Enum {DataType} is not supported.");

        }
    }
}